using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using DataAccess;
using Task.Contracts;
using NHibernate;
using NHibernate.Expression;

namespace Task
{
    /// <summary>
    /// Task for forum operations
    /// </summary>
    public sealed class ForumTask : IForumTask
    {

        /// <summary>
        /// Adds the forum.
        /// </summary>
        /// <param name="forumTemp">The forum temp.</param>
		/// 

		public int CountTopicsInForum(int forum_id)
			{
			string txt = "0";
			ISession session = NHibernateSessionManager.Instance.GetSession();
			IList result = session.Find("select count(cmt.id) from comment as cmt join cmt.forum as frm where frm.id='" + forum_id.ToString() + "' and cmt.comment_id is null");
			foreach (object o in result)
				{
				txt = o.ToString();
				}
			return Int32.Parse(txt);
			}

		public int CountCommentsInTopic(int forum_id, int parrentComment_id)
			{
			string txt = "0";
			ISession session = NHibernateSessionManager.Instance.GetSession();
			IList result = session.Find("select count(cmt.id) from comment as cmt join cmt.forum as frm where frm.id=" + forum_id.ToString() + "and cmt.comment_id=" + parrentComment_id.ToString());
			foreach (object o in result)
				{
				txt = o.ToString();
				}
			return Int32.Parse(txt);
			}

		public comment NewestCommentInTopic(int parentComment_id)
			{
			NHibernate.Expression.ICriterion[] criterion = new ICriterion[1];
			criterion[0] = NHibernate.Expression.Expression.Eq("comment_id",parentComment_id);
			NHibernateDao<DataAccess.comment, int> sampleForumFactory = new NHibernateDao<DataAccess.comment, int>();
			List<comment> returnList = sampleForumFactory.GetByCriteria(0, 0, "date", false, criterion);
			if (returnList == null)
				return null;
			else if (returnList.Count>0)
				return returnList[0];
			else
				return null;
			}

		public List<comment> TopicListByDate(int forum_id)
			{
			NHibernate.Expression.ICriterion[] criterion = new ICriterion[2];
			criterion[0] = NHibernate.Expression.Expression.Eq("forum_id", forum_id);
			criterion[1] = NHibernate.Expression.Expression.IsNull("comment_id");
			NHibernateDao<DataAccess.comment, int> sampleForumFactory = new NHibernateDao<DataAccess.comment, int>();
			List<comment> returnList = sampleForumFactory.GetByCriteria(0, 0, "date", false, criterion);
			returnList.Sort(SortTopicsByNewestComment);
			return returnList;
			}

		public List<comment> CommentsForTopic(int parentComment_id, int start, int howMany)
			{
			NHibernate.Expression.ICriterion[] criterion = new ICriterion[1];
			criterion[0] = NHibernate.Expression.Expression.Eq("comment_id",parentComment_id);
			NHibernateDao<DataAccess.comment, int> sampleForumFactory = new NHibernateDao<DataAccess.comment, int>();
			List<comment> returnList = sampleForumFactory.GetByCriteria(start, howMany, "date", false, criterion);
			return returnList;
			}

		public int ForumOwnerId(int forum_id)
			{
			NHibernateDao<forum, int> sampleForumFactory = new NHibernateDao<DataAccess.forum, int>();
			forum tmp = sampleForumFactory.GetById(forum_id, false);
			
			return (int)tmp.owner_id;
			}

		public bool IsSignedUser(int forum_id, int user_id)
			{
			NHibernateDao<forum_to_User, int> sampleForumFactory = new NHibernateDao<DataAccess.forum_to_User, int>();
			NHibernate.Expression.ICriterion[] criterion = new ICriterion[2];
			criterion[0]=NHibernate.Expression.Expression.Eq("id_forum", forum_id);
			criterion[1] = NHibernate.Expression.Expression.Eq("id_user", user_id);
			List<forum_to_User> tmpList=sampleForumFactory.GetByCriteria(criterion);
			if (tmpList.Count > 0)
				{
				return true;
				}
			return false;
			}

		public int GetMyOwnerForumsCount(int ownerid)
			{
			string txt = "0";
			ISession session = NHibernateSessionManager.Instance.GetSession();
			IList result = session.Find("select count(frm.id) from forum as frm where frm.owner_id=" + ownerid.ToString());

			/*IList result2 = session.Find("Select from forum as frm left join frm.comments as comments");
			foreach (object o in result2)
				{
				
				object[] tab = (object[])o;
				for (int i = 0; i < tab.Length; i++)
					{
					txt += tab[i].ToString() +"\r\n";	
					}
				}
			txt += "koniec";
			return result.Count;
			 */
			foreach (object o in result)
				{
				txt = o.ToString();
				}
			return Int32.Parse(txt);
			}

		public int GetMyForumsCount(int userid)
			{
			string txt="0";
			ISession session = NHibernateSessionManager.Instance.GetSession();
			IList result = session.Find("select count(frm.id) from forum as frm join frm.forum_to_Users as ftu join ftu.user as usr where usr.id=" + userid.ToString());
			foreach (object o in result)
				{
				txt = o.ToString();
				}
			return Int32.Parse(txt);
			}
		
		public void AddForum(forum forumTemp, int userId)
        { 
            NHibernateDao<forum, int> sampleForumFactory = new NHibernateDao<DataAccess.forum, int>();
			NHibernateDao<user, int> sampleUserFactory = new NHibernateDao<user, int>();
			
			user tmpUser = sampleUserFactory.GetById(userId, false);
			forumTemp.user = tmpUser; //trzeba tak a nie przez podawanie id jako int, nie wiem czemu, ale jesli sie tak zrobi to sie nie wali, to juz kiedys wyszlo
			sampleForumFactory.SaveOrUpdate(forumTemp);
			sampleForumFactory.CommitChanges();
        }

		public void SignToForum(int user_id, int forum_id)
			{
			
			NHibernateDao<forum_to_User, int> sampleForumToUserFactory = new NHibernateDao<DataAccess.forum_to_User, int>();
			NHibernateDao<user, int> sampleUserFactory = new NHibernateDao<DataAccess.user, int>();
			NHibernateDao<forum, int> sampleForumFactory = new NHibernateDao<DataAccess.forum, int>();
			
			NHibernate.Expression.ICriterion[] criterion = new ICriterion[2];
			criterion[0] = NHibernate.Expression.Expression.Eq("id_forum", forum_id);
			criterion[1] = NHibernate.Expression.Expression.Eq("id_user", user_id);
			List<forum_to_User> tmpList = sampleForumToUserFactory.GetByCriteria(criterion);

			if (tmpList.Count < 1)
				{
				forum frm = sampleForumFactory.GetById(forum_id, false);
				user usr = sampleUserFactory.GetById(user_id, false);
				forum_to_User ftu = new forum_to_User();
				ftu.forum = frm;
				ftu.user = usr;
				sampleForumToUserFactory.Save(ftu);
				}
			}

		public void unSignFromForum(int user_id, int forum_id)
			{
			NHibernateDao<forum_to_User, int> sampleForumToUserFactory = new NHibernateDao<DataAccess.forum_to_User, int>();
			NHibernateDao<user, int> sampleUserFactory = new NHibernateDao<DataAccess.user, int>();
			NHibernateDao<forum, int> sampleForumFactory = new NHibernateDao<DataAccess.forum, int>();
			NHibernate.Expression.ICriterion[] criterion = new ICriterion[2];
			criterion[0] = NHibernate.Expression.Expression.Eq("id_forum", forum_id);
			criterion[1] = NHibernate.Expression.Expression.Eq("id_user", user_id);
			List<forum_to_User> tmpList = sampleForumToUserFactory.GetByCriteria(criterion);
			if (tmpList.Count > 0)
				{
				user u = sampleUserFactory.GetById(tmpList[0].id_user,false);
				forum f = sampleForumFactory.GetById(tmpList[0].id_forum,false);
				u.forum_to_Users.Remove(tmpList[0]);
				f.forum_to_Users.Remove(tmpList[0]);
				sampleUserFactory.SaveOrUpdate(u);
				sampleForumFactory.SaveOrUpdate(f);
				sampleForumToUserFactory.Delete(tmpList[0]);
				sampleForumToUserFactory.CommitChanges();
				}
			}

		public List<DataAccess.forum> GetAllForums()
			{
			//NHibernateDao<forum, int> sampleForumFactory = new NHibernateDao<DataAccess.forum, int>();
			//return sampleForumFactory.GetAll();
			NHibernateDao<user, int> sampleUserFactory = new NHibernateDao<user, int>();
			user tmpUser = sampleUserFactory.GetById(2, false);
			IList<DataAccess.forum_to_User> forums = tmpUser.forum_to_Users;
			List<DataAccess.forum> returnList = new List<DataAccess.forum>();
			foreach (DataAccess.forum_to_User ftu in forums)
				{
				returnList.Add(ftu.forum);
				}
			return returnList;
			}

		public List<DataAccess.forum> GetOwnedForums(int start, int howMany, int user_id)
			{
			NHibernateDao<user, int> sampleUserFactory = new NHibernateDao<user, int>();
			user tmpUser = sampleUserFactory.GetById(user_id, false);
			List<DataAccess.forum> returnList = new List<forum>();
			returnList.AddRange(tmpUser.forums);
			returnList.Sort(SortForumByNewestComent);



			if (howMany <= returnList.Count - start)
				return returnList.GetRange(start, howMany);
			else
				return returnList.GetRange(start, returnList.Count - start);
			 
			}

		public List<DataAccess.comment> GetComments(int forumId, int start, int howMany)
			{
			NHibernate.Expression.ICriterion criterion= NHibernate.Expression.Expression.Eq("forum_id", forumId);
			NHibernateDao<DataAccess.comment, int> sampleForumFactory = new NHibernateDao<DataAccess.comment, int>();
			return sampleForumFactory.GetByCriteria(start,howMany,"date",false,criterion);
			}

		public List<DataAccess.comment> GetCommentsForParentComment(int forumId, int parentComment_id, int start, int howMany)
			{
			NHibernate.Expression.ICriterion[] criterion = new ICriterion[2];
			criterion[0] = NHibernate.Expression.Expression.Eq("comment_id", parentComment_id);
			criterion[1] = NHibernate.Expression.Expression.Eq("forum_id", forumId);
			NHibernateDao<DataAccess.comment, int> sampleForumFactory = new NHibernateDao<DataAccess.comment, int>();
			List<comment> returnList = sampleForumFactory.GetByCriteria(start, howMany, "date", true, criterion);
			return returnList;
			}

		public List<DataAccess.forum> GetForumsByNewestComment(int start, int howMany)
			{
			NHibernateDao<DataAccess.comment, int> sampleCommentFactory = new NHibernateDao<DataAccess.comment, int>();
			NHibernateDao<DataAccess.forum, int> sampleForumFactory = new NHibernateDao<DataAccess.forum, int>();
			NHibernate.Expression.ICriterion criterion = NHibernate.Expression.Expression.IsNotNull("forum_id");
			List<DataAccess.comment> tmpList = sampleCommentFactory.GetByCriteria(start, howMany,"date",true,criterion);
			List<DataAccess.forum> returnList = new List<forum>();
			List<int> uniqueIds = new List<int>();
			foreach (comment cmn in tmpList)
				{
				if (cmn.forum_id != null)
					{
					int forum_id = (int)cmn.forum_id;
					if(!uniqueIds.Contains(forum_id))
						{
						returnList.Add(sampleForumFactory.GetById(forum_id, false));
						uniqueIds.Add(forum_id);
						}
					}
				}
			return returnList;
			}

		public List<DataAccess.forum> SearchForums(string searchedText)
			{
			/*
			NHibernateDao<DataAccess.forum, int> sampleForumFactory = new NHibernateDao<DataAccess.forum, int>();
			NHibernate.Expression.ICriterion criterion =NHibernate.Expression.Expression.Or(NHibernate.Expression.Expression.Like("name","%"+searchedText+"%"),
				NHibernate.Expression.Expression.Like("description","%"+searchedText+"%"));
			return sampleForumFactory.GetByCriteria(criterion);*/

			ISession session = NHibernateSessionManager.Instance.GetSession();
			ICriteria criteria = session.CreateCriteria(typeof(forum))
								.CreateAlias("user","usr")
								.Add(NHibernate.Expression.Expression.Or(NHibernate.Expression.Expression.Or(NHibernate.Expression.Expression.Like("name", "%" + searchedText + "%"),
				NHibernate.Expression.Expression.Like("description", "%" + searchedText + "%")),NHibernate.Expression.Expression.Like("usr.login", "%" + searchedText + "%")));
			List<forum> returnList = new List<forum>();
				returnList.AddRange(criteria.List<forum>());
			return returnList;
			}


		public List<DataAccess.forum> GetForumsByNewestCommentForUser(int start, int howMany, int user_id)
			{
			NHibernateDao<user, int> sampleUserFactory = new NHibernateDao<user, int>();
			user tmpUser = sampleUserFactory.GetById(user_id, false);
			IList<DataAccess.forum_to_User> forums = tmpUser.forum_to_Users;
			List<DataAccess.forum> returnList = new List<DataAccess.forum>();
			foreach (DataAccess.forum_to_User ftu in forums)
				{
				returnList.Add(ftu.forum);
				}

			returnList.Sort(SortForumByNewestComent);
			if (howMany <= returnList.Count - start)
				return returnList.GetRange(start, howMany);
			else
				return returnList;
			}

		public void DeleteOwnerForum(int user_id, int forum_id)
			{
			NHibernate.Expression.ICriterion[] criterion = new ICriterion[2];
			criterion[0]= NHibernate.Expression.Expression.Eq("owner_id", user_id);
			criterion[1] = NHibernate.Expression.Expression.Eq("id", forum_id);
			NHibernateDao<DataAccess.forum, int> sampleForumFactory = new NHibernateDao<DataAccess.forum, int>();
			List<forum> lf = sampleForumFactory.GetByCriteria(criterion);
			if (lf.Count > 0)
				{
				sampleForumFactory.Delete(lf[0]);
				sampleForumFactory.CommitChanges();
				}
			}

		public List<DataAccess.comment> GetComments(DataAccess.forum forum, int start, int howMany)
			{
			List<DataAccess.comment> returnList = GetComments(forum.id, start, howMany);
			return returnList;
			}

		public int AddComment(DataAccess.forum forum, DataAccess.user user, DataAccess.comment comment)
			{
			NHibernateDao<DataAccess.comment, int> sampleCommentFactory = new NHibernateDao<DataAccess.comment, int>();
			comment.user = user;
			comment.forum = forum;
			return (sampleCommentFactory.SaveOrUpdate(comment)).id;
			}

		public int AddComment(int forum_id, int user_id, DataAccess.comment comment, params int[] parentCommentId)
			{
			NHibernateDao<DataAccess.user, int> sampleUserFactory = new NHibernateDao<DataAccess.user, int>();
			NHibernateDao<DataAccess.forum, int> sampleForumFactory = new NHibernateDao<DataAccess.forum, int>();
			NHibernateDao<DataAccess.comment, int> sampleCommentFactory = new NHibernateDao<DataAccess.comment, int>();
			if (parentCommentId != null)
				{
				if (parentCommentId.Length > 0) 
					{
					comment.commentParent = sampleCommentFactory.GetById(parentCommentId[0], false);
					}
				}
			return this.AddComment(sampleForumFactory.GetById(forum_id,false), sampleUserFactory.GetById(user_id,false), comment);
			}

		private static int SortForumByNewestComent(forum x, forum y)
			{
			comment topDateX=null;
			comment topDateY=null;

			NHibernateDao<DataAccess.comment, int> sampleCommentFactory = new NHibernateDao<DataAccess.comment, int>();
			NHibernate.Expression.ICriterion criterion = NHibernate.Expression.Expression.Eq("forum_id",x.id);
			
			List<comment> Comments = sampleCommentFactory.GetByCriteria(0, 1, "date",true, criterion);
			if(Comments.Count>0)
				topDateX = Comments[0];

			criterion = NHibernate.Expression.Expression.Eq("forum_id", y.id);
			Comments = sampleCommentFactory.GetByCriteria(0, 1, "date",true, criterion);
			if (Comments.Count > 0)
				topDateY = Comments[0];

			if (topDateX != null && topDateY != null)
				return ((DateTime)(topDateX.date).Value).CompareTo((DateTime)(topDateY.date).Value);
			else if (topDateY == null && topDateX == null)
				return 0;
			else if (topDateY == null)
				return -1;
			else if (topDateX == null)
				return 1;

			return 0;

			}

		private static int SortTopicsByNewestComment(comment x, comment y)
			{
			comment topDateX = null;
			comment topDateY = null;

			NHibernateDao<DataAccess.comment, int> sampleCommentFactory = new NHibernateDao<DataAccess.comment, int>();
			NHibernate.Expression.ICriterion criterion = NHibernate.Expression.Expression.Eq("comment_id", x.id);

			List<comment> Comments = sampleCommentFactory.GetByCriteria(0, 1, "date", true, criterion);
			if (Comments.Count > 0)
				topDateX = Comments[0];

			criterion = NHibernate.Expression.Expression.Eq("comment_id", y.id);
			Comments = sampleCommentFactory.GetByCriteria(0, 1, "date", true, criterion);
			if (Comments.Count > 0)
				topDateY = Comments[0];

			if (topDateX != null && topDateY != null)
				return ((DateTime)(topDateX.date).Value).CompareTo((DateTime)(topDateY.date).Value);
			else if (topDateY == null && topDateX == null)
				return -((DateTime)(x.date).Value).CompareTo((DateTime)(y.date).Value);
			else if (topDateY == null)
				return -1;
			else if (topDateX == null)
				return 1;

			return 0;

			}


		#region IForumTask Members


		public int GetCommentsCount(int forum_id)
			{
			throw new Exception("The method or operation is not implemented.");
			}

		#endregion
		}
}
